"""
研究质量评估服务实现

提供多维度的研究质量评估功能，包括：
- 研究质量评分
- 问题识别
- 改进建议生成
- 效果跟踪
"""
import math
from typing import List, Dict, Any, Optional, Tuple
from datetime import datetime
from dataclasses import asdict

from ..models.analysis_models import (
    QualityAssessment, QualityIssue, Improvement, ResearchResults,
    FailureReason, EffectReport
)
from ..models.research_models import ResearchPlan
from ..models.collaboration_models import Version


class ResearchQualityAssessmentService:
    """研究质量评估服务"""
    
    def __init__(self):
        self.assessment_criteria = {
            'methodology': {
                'weight': 0.25,
                'sub_criteria': {
                    'design_rigor': 0.4,
                    'data_quality': 0.3,
                    'analysis_validity': 0.3
                }
            },
            'novelty': {
                'weight': 0.20,
                'sub_criteria': {
                    'originality': 0.5,
                    'innovation': 0.3,
                    'contribution': 0.2
                }
            },
            'impact': {
                'weight': 0.20,
                'sub_criteria': {
                    'theoretical_impact': 0.4,
                    'practical_impact': 0.4,
                    'societal_impact': 0.2
                }
            },
            'reproducibility': {
                'weight': 0.15,
                'sub_criteria': {
                    'code_availability': 0.4,
                    'data_availability': 0.3,
                    'documentation_quality': 0.3
                }
            },
            'presentation': {
                'weight': 0.10,
                'sub_criteria': {
                    'clarity': 0.4,
                    'organization': 0.3,
                    'completeness': 0.3
                }
            },
            'ethics': {
                'weight': 0.10,
                'sub_criteria': {
                    'ethical_compliance': 0.6,
                    'bias_consideration': 0.4
                }
            }
        }
    
    async def assess_research_quality(self, research_data: Dict[str, Any]) -> QualityAssessment:
        """评估研究质量"""
        try:
            # 初始化评估结果
            assessment = QualityAssessment()
            
            # 评估各个维度
            for dimension, config in self.assessment_criteria.items():
                dimension_score = await self._assess_dimension(
                    dimension, research_data, config
                )
                assessment.add_dimension_score(dimension, dimension_score)
            
            # 计算综合评分
            overall_score = assessment.calculate_overall_score()
            
            # 识别优势和劣势
            strengths, weaknesses = await self._identify_strengths_weaknesses(
                assessment.dimension_scores
            )
            assessment.strengths = strengths
            assessment.weaknesses = weaknesses
            
            # 生成改进建议
            improvement_suggestions = await self._generate_improvement_suggestions(
                assessment.dimension_scores, weaknesses
            )
            assessment.improvement_suggestions = improvement_suggestions
            
            # 设置评估标准
            assessment.assessment_criteria = list(self.assessment_criteria.keys())
            
            return assessment
            
        except Exception as e:
            print(f"研究质量评估失败: {e}")
            # 返回默认评估结果
            return QualityAssessment()
    
    async def _assess_dimension(self, dimension: str, research_data: Dict[str, Any], 
                               config: Dict[str, Any]) -> float:
        """评估单个维度的质量"""
        if dimension == 'methodology':
            return await self._assess_methodology(research_data, config['sub_criteria'])
        elif dimension == 'novelty':
            return await self._assess_novelty(research_data, config['sub_criteria'])
        elif dimension == 'impact':
            return await self._assess_impact(research_data, config['sub_criteria'])
        elif dimension == 'reproducibility':
            return await self._assess_reproducibility(research_data, config['sub_criteria'])
        elif dimension == 'presentation':
            return await self._assess_presentation(research_data, config['sub_criteria'])
        elif dimension == 'ethics':
            return await self._assess_ethics(research_data, config['sub_criteria'])
        else:
            return 0.5  # 默认中等分数
    
    async def _assess_methodology(self, research_data: Dict[str, Any], 
                                 sub_criteria: Dict[str, float]) -> float:
        """评估方法论质量"""
        scores = {}
        
        # 设计严谨性
        design_rigor = 0.5
        if 'experimental_design' in research_data:
            design = research_data['experimental_design']
            if isinstance(design, dict):
                # 检查控制变量
                if design.get('control_variables'):
                    design_rigor += 0.2
                # 检查样本大小
                if design.get('sample_size', 0) > 100:
                    design_rigor += 0.2
                # 检查随机化
                if design.get('randomization'):
                    design_rigor += 0.1
        scores['design_rigor'] = min(1.0, design_rigor)
        
        # 数据质量
        data_quality = 0.5
        if 'data_info' in research_data:
            data_info = research_data['data_info']
            if isinstance(data_info, dict):
                # 检查数据完整性
                completeness = data_info.get('completeness', 0.5)
                data_quality = completeness
                # 检查数据来源可靠性
                if data_info.get('reliable_source'):
                    data_quality += 0.2
        scores['data_quality'] = min(1.0, data_quality)
        
        # 分析有效性
        analysis_validity = 0.5
        if 'analysis_methods' in research_data:
            methods = research_data['analysis_methods']
            if isinstance(methods, list) and len(methods) > 0:
                # 检查方法适用性
                analysis_validity = 0.7
                # 检查统计显著性
                if any('statistical_test' in str(method) for method in methods):
                    analysis_validity += 0.2
        scores['analysis_validity'] = min(1.0, analysis_validity)
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _assess_novelty(self, research_data: Dict[str, Any], 
                             sub_criteria: Dict[str, float]) -> float:
        """评估新颖性"""
        scores = {}
        
        # 原创性
        originality = 0.5
        if 'literature_review' in research_data:
            lit_review = research_data['literature_review']
            if isinstance(lit_review, dict):
                # 检查文献覆盖度
                coverage = lit_review.get('coverage_score', 0.5)
                # 检查研究空白识别
                gaps_identified = len(lit_review.get('research_gaps', []))
                originality = min(1.0, coverage + gaps_identified * 0.1)
        scores['originality'] = originality
        
        # 创新性
        innovation = 0.5
        if 'innovation_aspects' in research_data:
            aspects = research_data['innovation_aspects']
            if isinstance(aspects, list):
                innovation = min(1.0, 0.3 + len(aspects) * 0.2)
        scores['innovation'] = innovation
        
        # 贡献度
        contribution = 0.5
        if 'contributions' in research_data:
            contributions = research_data['contributions']
            if isinstance(contributions, list):
                contribution = min(1.0, 0.3 + len(contributions) * 0.15)
        scores['contribution'] = contribution
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _assess_impact(self, research_data: Dict[str, Any], 
                            sub_criteria: Dict[str, float]) -> float:
        """评估影响力"""
        scores = {}
        
        # 理论影响
        theoretical_impact = 0.5
        if 'theoretical_contributions' in research_data:
            contributions = research_data['theoretical_contributions']
            if isinstance(contributions, list) and len(contributions) > 0:
                theoretical_impact = min(1.0, 0.4 + len(contributions) * 0.2)
        scores['theoretical_impact'] = theoretical_impact
        
        # 实践影响
        practical_impact = 0.5
        if 'practical_applications' in research_data:
            applications = research_data['practical_applications']
            if isinstance(applications, list) and len(applications) > 0:
                practical_impact = min(1.0, 0.4 + len(applications) * 0.2)
        scores['practical_impact'] = practical_impact
        
        # 社会影响
        societal_impact = 0.5
        if 'societal_benefits' in research_data:
            benefits = research_data['societal_benefits']
            if isinstance(benefits, list) and len(benefits) > 0:
                societal_impact = min(1.0, 0.4 + len(benefits) * 0.3)
        scores['societal_impact'] = societal_impact
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _assess_reproducibility(self, research_data: Dict[str, Any], 
                                     sub_criteria: Dict[str, float]) -> float:
        """评估可重现性"""
        scores = {}
        
        # 代码可用性
        code_availability = 0.0
        if research_data.get('code_available'):
            code_availability = 0.8
            if research_data.get('code_documented'):
                code_availability = 1.0
        scores['code_availability'] = code_availability
        
        # 数据可用性
        data_availability = 0.0
        if research_data.get('data_available'):
            data_availability = 0.7
            if research_data.get('data_documented'):
                data_availability = 1.0
        scores['data_availability'] = data_availability
        
        # 文档质量
        documentation_quality = 0.5
        if 'documentation' in research_data:
            doc_info = research_data['documentation']
            if isinstance(doc_info, dict):
                completeness = doc_info.get('completeness', 0.5)
                clarity = doc_info.get('clarity', 0.5)
                documentation_quality = (completeness + clarity) / 2
        scores['documentation_quality'] = documentation_quality
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _assess_presentation(self, research_data: Dict[str, Any], 
                                  sub_criteria: Dict[str, float]) -> float:
        """评估表达质量"""
        scores = {}
        
        # 清晰度
        clarity = 0.5
        if 'writing_quality' in research_data:
            writing = research_data['writing_quality']
            if isinstance(writing, dict):
                clarity = writing.get('clarity_score', 0.5)
        scores['clarity'] = clarity
        
        # 组织结构
        organization = 0.5
        if 'structure_quality' in research_data:
            structure = research_data['structure_quality']
            if isinstance(structure, dict):
                organization = structure.get('organization_score', 0.5)
        scores['organization'] = organization
        
        # 完整性
        completeness = 0.5
        if 'content_completeness' in research_data:
            completeness = research_data['content_completeness']
        scores['completeness'] = completeness
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _assess_ethics(self, research_data: Dict[str, Any], 
                            sub_criteria: Dict[str, float]) -> float:
        """评估伦理合规性"""
        scores = {}
        
        # 伦理合规
        ethical_compliance = 0.5
        if research_data.get('ethics_approval'):
            ethical_compliance = 1.0
        elif research_data.get('ethics_considered'):
            ethical_compliance = 0.7
        scores['ethical_compliance'] = ethical_compliance
        
        # 偏见考虑
        bias_consideration = 0.5
        if 'bias_analysis' in research_data:
            bias_info = research_data['bias_analysis']
            if isinstance(bias_info, dict):
                if bias_info.get('bias_identified'):
                    bias_consideration = 0.8
                if bias_info.get('bias_mitigated'):
                    bias_consideration = 1.0
        scores['bias_consideration'] = bias_consideration
        
        # 计算加权平均
        weighted_score = sum(scores[key] * weight for key, weight in sub_criteria.items())
        return weighted_score
    
    async def _identify_strengths_weaknesses(self, dimension_scores: Dict[str, float]) -> Tuple[List[str], List[str]]:
        """识别研究的优势和劣势"""
        strengths = []
        weaknesses = []
        
        # 定义阈值
        strength_threshold = 0.8
        weakness_threshold = 0.6
        
        dimension_names = {
            'methodology': '方法论',
            'novelty': '新颖性',
            'impact': '影响力',
            'reproducibility': '可重现性',
            'presentation': '表达质量',
            'ethics': '伦理合规'
        }
        
        for dimension, score in dimension_scores.items():
            dimension_name = dimension_names.get(dimension, dimension)
            
            if score >= strength_threshold:
                strengths.append(f"{dimension_name}表现优秀 (评分: {score:.2f})")
            elif score < weakness_threshold:
                weaknesses.append(f"{dimension_name}需要改进 (评分: {score:.2f})")
        
        return strengths, weaknesses
    
    async def _generate_improvement_suggestions(self, dimension_scores: Dict[str, float], 
                                              weaknesses: List[str]) -> List[str]:
        """生成改进建议"""
        suggestions = []
        
        for dimension, score in dimension_scores.items():
            if score < 0.6:  # 需要改进的维度
                if dimension == 'methodology':
                    suggestions.extend([
                        "加强实验设计的严谨性，增加控制变量",
                        "提高数据质量，确保数据完整性和可靠性",
                        "选择更适合的分析方法，进行统计显著性检验"
                    ])
                elif dimension == 'novelty':
                    suggestions.extend([
                        "深入分析现有文献，识别更多研究空白",
                        "突出研究的创新点和独特贡献",
                        "明确阐述研究的原创性价值"
                    ])
                elif dimension == 'impact':
                    suggestions.extend([
                        "加强理论贡献的阐述",
                        "明确实践应用价值",
                        "考虑研究的社会影响和意义"
                    ])
                elif dimension == 'reproducibility':
                    suggestions.extend([
                        "提供完整的代码和数据",
                        "改善文档质量，增加实现细节",
                        "确保实验可重现性"
                    ])
                elif dimension == 'presentation':
                    suggestions.extend([
                        "提高写作清晰度，避免模糊表述",
                        "优化文章结构和逻辑组织",
                        "确保内容完整性"
                    ])
                elif dimension == 'ethics':
                    suggestions.extend([
                        "获得必要的伦理审批",
                        "分析和缓解潜在偏见",
                        "确保研究符合伦理标准"
                    ])
        
        # 去重并限制数量
        unique_suggestions = list(set(suggestions))
        return unique_suggestions[:10]  # 最多返回10个建议
    
    async def generate_assessment_report(self, assessment: QualityAssessment, 
                                       research_data: Dict[str, Any]) -> str:
        """生成评估报告"""
        report_lines = [
            "# 研究质量评估报告",
            f"评估时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"综合评分: {assessment.overall_score:.2f}/1.00 ({assessment.get_grade()})",
            "",
            "## 维度评分",
        ]
        
        # 添加各维度评分
        dimension_names = {
            'methodology': '方法论',
            'novelty': '新颖性', 
            'impact': '影响力',
            'reproducibility': '可重现性',
            'presentation': '表达质量',
            'ethics': '伦理合规'
        }
        
        for dimension, score in assessment.dimension_scores.items():
            dimension_name = dimension_names.get(dimension, dimension)
            report_lines.append(f"- {dimension_name}: {score:.2f}")
        
        # 添加优势
        if assessment.strengths:
            report_lines.extend([
                "",
                "## 研究优势",
            ])
            for strength in assessment.strengths:
                report_lines.append(f"- {strength}")
        
        # 添加劣势
        if assessment.weaknesses:
            report_lines.extend([
                "",
                "## 需要改进的方面",
            ])
            for weakness in assessment.weaknesses:
                report_lines.append(f"- {weakness}")
        
        # 添加改进建议
        if assessment.improvement_suggestions:
            report_lines.extend([
                "",
                "## 改进建议",
            ])
            for i, suggestion in enumerate(assessment.improvement_suggestions, 1):
                report_lines.append(f"{i}. {suggestion}")
        
        # 添加总结
        report_lines.extend([
            "",
            "## 总结",
            f"本研究在{len(assessment.strengths)}个方面表现优秀，",
            f"在{len(assessment.weaknesses)}个方面需要改进。",
            f"建议重点关注{assessment.improvement_suggestions[:3] if assessment.improvement_suggestions else ['整体质量提升']}。"
        ])
        
        return "\n".join(report_lines)
    
    async def compare_assessments(self, assessment1: QualityAssessment, 
                                assessment2: QualityAssessment) -> Dict[str, Any]:
        """比较两次评估结果"""
        comparison = {
            'overall_score_change': assessment2.overall_score - assessment1.overall_score,
            'dimension_changes': {},
            'improvement_areas': [],
            'regression_areas': []
        }
        
        # 比较各维度变化
        for dimension in assessment1.dimension_scores:
            if dimension in assessment2.dimension_scores:
                change = assessment2.dimension_scores[dimension] - assessment1.dimension_scores[dimension]
                comparison['dimension_changes'][dimension] = change
                
                if change > 0.1:  # 显著改进
                    comparison['improvement_areas'].append(dimension)
                elif change < -0.1:  # 显著退步
                    comparison['regression_areas'].append(dimension)
        
        return comparison
    
    async def track_quality_trends(self, assessments: List[QualityAssessment]) -> Dict[str, Any]:
        """跟踪质量趋势"""
        if len(assessments) < 2:
            return {'error': '需要至少两次评估结果'}
        
        trends = {
            'overall_trend': [],
            'dimension_trends': {},
            'improvement_rate': 0.0,
            'stable_dimensions': [],
            'volatile_dimensions': []
        }
        
        # 计算整体趋势
        overall_scores = [assessment.overall_score for assessment in assessments]
        trends['overall_trend'] = overall_scores
        
        # 计算改进率
        if len(overall_scores) > 1:
            initial_score = overall_scores[0]
            final_score = overall_scores[-1]
            if initial_score > 0:
                trends['improvement_rate'] = (final_score - initial_score) / initial_score * 100
        
        # 分析各维度趋势
        all_dimensions = set()
        for assessment in assessments:
            all_dimensions.update(assessment.dimension_scores.keys())
        
        for dimension in all_dimensions:
            dimension_scores = []
            for assessment in assessments:
                if dimension in assessment.dimension_scores:
                    dimension_scores.append(assessment.dimension_scores[dimension])
            
            if len(dimension_scores) > 1:
                trends['dimension_trends'][dimension] = dimension_scores
                
                # 计算方差判断稳定性
                mean_score = sum(dimension_scores) / len(dimension_scores)
                variance = sum((score - mean_score) ** 2 for score in dimension_scores) / len(dimension_scores)
                
                if variance < 0.01:  # 低方差表示稳定
                    trends['stable_dimensions'].append(dimension)
                elif variance > 0.05:  # 高方差表示波动大
                    trends['volatile_dimensions'].append(dimension)
        
        return trends